/**
 * useDeferredValue() - 获取一个延迟的值
 *    作用：
 *      性能优化相关的hook,能够降级某次状态更新的优先级。 useTransition()
 *    语法：
 *      const deferredValue = useDeferredValue(value)
 *        1. value - 要基于的数据，一般是一个 state 或 prop 的数据
 *        2. deferredValue - 是基于 value 的一个延迟值。
 *           1. 初始化阶段，deferredValue 的值 等于 value
 *           2. 更新阶段，如果 value 有更新的话，deferredValue 会引起组件两种更新
 *              1. 第一次的值是 value 的上一次的值
 *              2. 第二次的值是 value 最新的值
 *    案例：
 *      实现搜索功能，搜索结果故意做一些延迟，发现搜素有阻塞问题，使用 useDeferredValue 解决这个阻塞问题
 *
 *      1. 需要通过 memo 对有性能问题的组件做一个缓存。避免没必要的重新Render
 *      2. 需要通过 useDeferredValue 对 query 状态做一个延迟，给到 SearchList 组件去使用
 *
 *        过程如下：
 *          1. 初始化时，SearchList 组件接受到的 query 为 '', 它需要Render，页面会卡顿3秒
 *          2. 输入框输入一个1, App 组件的 query 值直接更新为 1. 而 deferredQuery 还是上一次的 '', 该 '' 给到 SearchList 组件，该组件由于处理的 memo .判断上次收到的 '' 和 这次的 '' 没有变化，组件不会Render。不会就不引起input输入框的卡顿，输入框能够直接响应输入。
 *             deferredQuery 引起App组件（当前所处）第二次更新，这次更新 deferredQuery 的值为 1 ，1 给到 SearchList 组件, 会引起 SearchList 组件的重新渲染。它会引起页面卡顿，但这时我的输入框已经渲染完1这个字符串了。
 *
 */

import { memo, useDeferredValue, useState } from "react";

// 定义一份写死的 todos 数据
const todos = Array(200)
  .fill("")
  .map((item, index) => `Todo #${index + 1}`);
console.log(todos);

const SearchList = memo(function SearchList({ query = "" }) {
  // 人为的卡顿3秒
  const startTime = Date.now();
  while (Date.now() - startTime < 3000) {}

  // 基于 todos 与 props 中传递过来的 query 先做一份过滤
  const list = todos.filter((item) => item.includes(query));

  return (
    <ul>
      {list.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
});

function App() {
  const [num, setNum] = useState(1);
  const [query, setQuery] = useState("");
  // 基于 query 生成一份延迟值
  const deferredQuery = useDeferredValue(query);

  return (
    <div>
      <h1>App</h1>
      <input
        type="text"
        placeholder="请输入搜索关键字"
        value={query}
        onChange={(event) => setQuery(event.target.value)}
      />
      <button onClick={() => setNum((num) => num + 1)}>{num}</button>
      <hr />
      <SearchList query={deferredQuery} />
    </div>
  );
}

// 演示，useDeferredValue 触发两次更新
// function App() {
//   const [num, setNum] = useState(1);
//   const [query, setQuery] = useState("张三");
//   const deferredQuery = useDeferredValue(query);

//   console.log("query", query);
//   console.log("deferredQuery", deferredQuery);

//   return (
//     <div>
//       <h1>App</h1>
//       <button onClick={() => setNum((num) => num + 1)}>{num}</button>
//       <button onClick={() => setQuery((query) => query + "!")}>{query}</button>
//     </div>
//   );
// }

export default App;
